package com.macrounion.atv.task;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.google.common.collect.Lists;
import com.macrounion.atv.cache.ChannelCache;
import com.macrounion.atv.cache.CurrentDataCache;
import com.macrounion.atv.processor.RegProcessor;
import com.macrounion.atv.processor.SettingsProcessor;
import com.macrounion.atv.service.entity.Channel;
import com.macrounion.atv.service.entity.CurrentData;
import com.macrounion.atv.service.entity.Device;
import com.macrounion.atv.service.entity.Settings;
import com.macrounion.atv.service.service.ChannelService;
import com.macrounion.atv.service.service.DeviceService;
import com.macrounion.atv.socket.SendConnectionProcessor;
import com.macrounion.base.service.utils.DateUtils;

import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

/**
 * snmp协议数据刷新
 * @author Administrator
 *
 */
@Component
public class SendTask implements Job{
	
	@Autowired
	private SendConnectionProcessor sendConnectionProcessor;
	@Autowired
	private CacheManager manager;
	@Autowired
	private CurrentDataCache currentDataCache;
	@Autowired
	private ChannelCache channelCache;
	@Autowired
	private ChannelService channelService;
	@Autowired
	private DeviceService deviceService;
	@Autowired
	private RegProcessor regProcessor;
	@Autowired
	private SettingsProcessor settingsProcessor;
	@Value("${timely.outTimeSendHistory:false}")
	private boolean outtimeSendHistory;
	
	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
//		return;
		if(!regProcessor.canUse())
			return;
		JobKey key = context.getJobDetail().getKey();
		net.sf.ehcache.Cache cache = manager.getCache("devices");
		Map<Object,Element> maps = cache.getAll(cache.getKeys());
		if(maps == null || CollectionUtils.isEmpty(maps.values())) {
				return;
		}
		StringBuilder  sb = new StringBuilder();
		List<Element> es = new ArrayList<>(maps.values());
		es.forEach(e->{
			Device d = (Device) e.getObjectValue();
			sb.append(convert(d));
//			System.out.println(d.getName());
		});
		String content = sb.toString();
		if(!StringUtils.isEmpty(content))
			sendConnectionProcessor.sendHistory(key.getName(),sb.toString());
	}

	/**
	 * 格式化历史数据
	 * @param d
	 * @return
	 */
	private String convert(Device d) {
		if(d == null)
			return "";
		List<CurrentData> datas = new ArrayList<CurrentData>(currentDataCache.getCurrentData(d.getId()));
//		List<CurrentData> datas = currentDataCache.getCurrentData(d.getId()); //线程不安全
		if(CollectionUtils.isEmpty(datas))
			return "";
		if(!outtimeSendHistory) {
			//超时通道不发送
			datas = datas.parallelStream().filter(data->{
				return data.getCreatedTime() == null || DateUtils.addMinute(data.getCreatedTime(), d.getTimeout() == null?5:d.getTimeout()).after(new Date());
			}).collect(Collectors.toList());
			if(CollectionUtils.isEmpty(datas))
				return "";
		}
		StringBuilder  sb = new StringBuilder();
		sb.append("<OMMHISTORY>");
		sb.append("<IP>"+deviceService.getDeviceIp(d)+"</IP>");
		datas.forEach(data->{
				sb.append(getXmlString(d,data));
		});
		sb.append("<prold>"+getDevice()+"</prold>");
		sb.append("</OMMHISTORY>");
		if(sb.toString().indexOf("<CH") < 0)
			return "";
		return sb.toString();
	}

	/**
	 * 本设备唯一号
	 * @return
	 */
	private String getDevice() {
		Settings set = settingsProcessor.findByName("serverId");
		return set != null?(StringUtils.isEmpty(set.getValues())?"":set.getValues()):"";
	}

	private String getXmlString(Device d, CurrentData data) {
		if(data.getChannelCode().toLowerCase().startsWith("t"))
			return "";
		Channel c = channelCache.getChannel(data.getDeviceId(), data.getChannelCode());
		if(c == null)
			return "";
		if(d.getSendType().equals(1) && c.getHistoryData().equals(0))
			return "";
		String channelCode = channelService.getChannelCode(data.getChannelCode());
		String resp = "<CH"+channelCode+">"
					+ "<N>"+c.getName()+"</N>"
					+ "<V>"+data.getShowValue()+"</V>"
					+ "<U>"+(data.getUnit()==null?"":data.getUnit())+"</U>"
					+ "<AD>"+c.getDataType()+"</AD>"
					+ "<AL>"+data.getAlarm()+"</AL>"
					+ "</CH"+channelCode+">";
		return resp;
	}
}
